#include <stdint.h>

/**
  Header file for the encrypt/decrypt test harness CICM library.
  @file CICM.h
  @version 0.1
  @date 2011-03-04
  @see http://tools.ietf.org/html/draft-lanz-cicm
  @see http://tools.ietf.org/html/draft-lanz-cicm-mm
  @see http://tools.ietf.org/html/draft-lanz-cicm-km
  @see http://tools.ietf.org/html/draft-lanz-cicm-cm
*/
namespace CICM {
  typedef uint32_t UInt32;     /** @see CICM 2.2.1 */
  typedef UInt32 Status;       /** @see CICM 2.2.3 */
  typedef UInt32 RemotePort;   /** @see CICM 2.2.5 */

  typedef char * CharString;   /** @see CICM 2.2.1 */
  typedef CharString ModuleId; /** @see CICM 2.2.2 */
  typedef CharString KeyId;    /** @see CICM-KM 3.6 */
  typedef CharString SymEncrAlgorithmId; /** @see CICM-CM 4.1 */

  /** @see CICM Appendix A. Status Codes */
  const CICM::Status S_OK = 0x00000000;

  /**
    @see CICM 2.2.1
    @see http://www.omg.org/spec/CPP/1.2/PDF
  */
  class Buffer {
    private:
      unsigned long len;
      unsigned long *data;

    public:
      // Constructor
      Buffer(unsigned long len, char *data);

      // Destructor
      ~Buffer(void);

      // No Copy Constructor

      // Overloaded Operators
      Buffer & operator=(const Buffer &);
      Buffer & operator[](unsigned long idx);
      char * operator[](unsigned long idx) const;
      bool operator==(const Buffer &other) const;

      // Methods
      unsigned long length(void) const;
      char * get_buffer(void) const;
  };

  //// Key Management ////

  /** @see CICM-KM 3.7 */
  class Key {};

  /** @see CICM-KM 5.2 */
  class SymKey : CICM::Key {};

  /** @see CICM-KM 5.1 */
  class SymKeyManager {
    public:
      CICM::Status get_key_by_id(
        CICM::KeyId& key_id,    // in
        CICM::SymKey** key_ref  // out
      );
  };//end: SymKeyManager

  //// Channel Management ////

  /** @see CICM-CM 4.5 */
  class Channel {};

  /** @see CICM-CM 4.7 */
  class Controller : public CICM::Channel {};

  /** @see CICM-CM 4.8 */
  class Stream : public CICM::Channel {};

  /** @see CICM-CM 4.6 */
  class Conduit :
    public CICM::Controller,
    public CICM::Stream {};

  /** @see CICM-CM 6.1 */
  class WriteStream : public CICM::Stream {};

  /** @see CICM-CM  6.2 */
  class ReadStream : public CICM::Stream {};

  /** @see CICM-CM 9*/
  namespace Encrypt {

    /** @see CICM-CM 9.4 */
    class Controller {};

    /** @see CICM-CM 9.2 */
    class Stream : public CICM::WriteStream {
      public:
        CICM::Status encrypt(CICM::Buffer*& buffer);
    };//end: CICM::Encrypt::Stream

    /** @see CICM-CM 9.6 */
    class Conduit :
      public CICM::Conduit,
      public CICM::Encrypt::Controller,
      public CICM::Encrypt::Stream {};

    /** @see CICM-CM 9.1 */
    class ChannelManager {
      public:
        CICM::Status create_encrypt_conduit(
          CICM::RemotePort& remote_port,        // in
          CICM::SymKey* key_ref,                // in
          CICM::SymEncrAlgorithmId& algorithm,  // in
          CICM::Encrypt::Conduit** conduit_ref  // out
        );
    };//end: CICM::Encrypt::ChannelManager
  };//end: CICM::Encrypt

  /** @see CICM-CM 10 */
  namespace Decrypt {

    /** @see CICM-CM 10.4 */
    class Controller {};

    /** @see CICM-CM 10.2 */
    class Stream : public CICM::ReadStream {
      public:
        CICM::Status decrypt(CICM::Buffer** buffer);
    };//end: CICM::Decrypt::Stream

    /** @see CICM-CM 10.6 */
    class Conduit :
      public CICM::Conduit,
      public CICM::Decrypt::Controller,
      public CICM::Decrypt::Stream {};

    /** @see CICM-CM 10.1 */
    class ChannelManager {
      public:
        CICM::Status create_decrypt_conduit(
          CICM::RemotePort& remote_port,        // in
          CICM::SymKey* key_ref,                // in
          CICM::SymEncrAlgorithmId& algorithm,  // in
          CICM::Decrypt::Conduit** conduit_ref  // out
        );
    };//end: CICM::Decrypt::ChannelManager
  };//end: CICM::Decrypt

  /** @see CICM-CM 4.4 */
  class ChannelManager :
    public CICM::Encrypt::ChannelManager,
    public CICM::Decrypt::ChannelManager {};

  //// Module Management ////

  /** @see CICM 2.3.2 */
  class CryptoModule {
    public:
      CICM::SymKeyManager* _get_sym_key_manager(void);
      CICM::ChannelManager* _get_channel_manager(void);

    private:
      /** @see CICM 2.3.2.1 */
      CICM::SymKeyManager sym_key_manager;
      CICM::ChannelManager channel_manager;
  };//end: CICM::CryptoModule

  /** @see CICM 2.3.1 */
  class CICMRoot {
    public:
      CICM::Status get_module_by_id(
        CICM::ModuleId& module_id,              // in
        CICM::CryptoModule** crypto_module_ref  // out
      );
  };//end: CICM::CICMRoot
};//end: CICM
